home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Programming Contest / !Problems < prev    next >
Encoding:
Text File  |  1998-06-20  |  17.2 KB  |  445 lines  |  [TEXT/R*ch]

  1. Problem 01 - Mode Sort
  2.  
  3. This problem is to sort an input string of N characters, N<1000000, based on
  4. the number of times a character occurs in the input.  The most frequently
  5. occurring character should be sorted to the front of the string, followed by
  6. the next most frequently occurring character, etc.  For characters occurring
  7. the same number of times, the character that occurs first in the input should
  8. be sorted to the front.
  9.  
  10. Header specification
  11.  
  12. pascal OSErr ModeSort( const FSSpec* infile, const FSSpec* outfile );
  13.  
  14. Input specification
  15.  
  16. The infile input file contains the characters.  Input characters other than
  17. those printable low ascii characters c, 0x20<c<0x7f, must be ignored.
  18.  
  19. Output specification
  20.  
  21. The outfile must be created and then filled with the sorted characters.  It's
  22. final length should be exactly the same as the count of characters in the
  23. allowed range (0x20<c<0x7f) (which may be shorter than the infile file length).
  24.  
  25. Sample input
  26.  
  27. abcdefghabbcccdddeee
  28. or
  29. 012345678911234567892123456789312345678941234567895123456789612345678971234567891
  30.  
  31. Sample output
  32.  
  33. ccccddddeeeebbbaafgh
  34. or
  35. 111111111122222222233333333344444444455555555566666666677777777788888888999999990
  36.  
  37. Problem 02 - Hower of Tanoi
  38.  
  39. This problem is to solve a variant of the Tower of Hanoi puzzle.  You remember
  40. the Tower of Hanoi, a board with three pegs, one of which has N disks of size
  41. 1, 2, 3, ... N, with the smallest disk at the top.  In the standard puzzle, the
  42. goal is to move all of the disks from one peg to another peg, by repeatedly
  43. moving a disk from the top of one peg to another peg without ever placing a
  44. larger disk on top of a smaller disk.
  45.  
  46. In our Hower of Tanoi problem, the objective and the constraints are the same,
  47. except that the disks on the first peg are initially in random order. You can
  48. still only move a smaller disk onto a larger disk.
  49.  
  50. Your objective is output the moves required to place all the disks on peg 3 in
  51. order with the smallest disk at the top.  
  52.  
  53. Input specification
  54.  
  55. The first line of the input file contains an integer M, M<1000, the number of
  56. disks in the problem.  The next M lines contain the numbers 1 .. M, one number
  57. per line, randomly ordered, where the first number is the size of the top disk
  58. on peg 1, the second number is the size of the 2nd disk from the top, etc.
  59.  
  60. Output specification
  61.  
  62. The output is a sequence of lines, each representing a single move,  consisting
  63. of the source peg number followed by a comma (',') followed by the destination
  64. peg number, followed by a return character.
  65.  
  66. Sample input
  67.  
  68. 2
  69. 2
  70. 1
  71.  
  72. Sample output
  73.  
  74. 1,3
  75. 1,3
  76.  
  77. Problem 03 - Perimeter
  78.  
  79. You are in charge of protecting a set of defenseless homeowners from predators
  80. that roam the area by constructing a single fence of minimum length that
  81. encloses all of the homes.  
  82.  
  83. The prototype for your solution is as follows:
  84.  
  85. typedef struct Node {
  86.     long xCoord;
  87.     long yCoord;
  88. } Node;
  89.  
  90. void Perimiter(
  91.     long numHomes,
  92.     Node homesToEnclose[],
  93.     long *numNodesInPerimiter,
  94.     long nodesInPerimiter[]
  95. );
  96.  
  97. You are given a list homesToEnclose of numHomes homes to protect  (numbered 0
  98. to numHomes-1) by constructing a fence around the homes. You should return a
  99. list nodesInPerimiter of the numNodesInPerimiter homes to be connected by a
  100. fence.  The fence must enclose all of the homes using the minimum amount of
  101. fencing material.
  102.  
  103.  
  104.  
  105. Problem 04 - Text Processing
  106.  
  107. const
  108.     kMaxHandleSize = 1000000;
  109. const
  110.     kActionMove = 1;
  111.     kActionInsert = 2;
  112.     kActionDelete = 3;
  113.     kActionSearch = 4;
  114.     kActionSearchAndReplace = 5;
  115. const
  116.     kFlagCaseSensitiveBit = 0;
  117.     kFlagGlobalBit = 1;
  118.     kFlagBackwardsBit = 2;
  119. type
  120.   ActionRecord = record
  121.     action: UInt32;
  122.     amount: SInt32;
  123.     flags: UInt32;
  124.     search: Str255;
  125.     replace: Str255;
  126.   end;
  127.   ActionRecordArray = array[0..0] of ActionRecord;
  128.   ActionRecordArrayPtr = ^ActionRecordArray;
  129.  
  130. procedure TextProcess( data: Handle; action_count: UInt32; actions:
  131. ActionRecordArrayPtr );
  132.  
  133. Given an unlocked handle to a block of text, you need to apply a sequence of
  134. actions to the data.  You will be required to insert text, delete text, search
  135. for text, search for and replace text.  All required actions take place at the
  136. position of the current selection pointer, which starts at zero, before the
  137. first character in the data.  In response to each of the action commands you
  138. need to perform the following:
  139.  
  140. kActionMove - move the internal position forward by the amount field (which may
  141. be negative).  (Example, kActionMove with amount set to kMaxHandleSize will set
  142. the internal pointer to be GetHandleSize( data )).
  143.  
  144. kActionInsert - Insert the replace string at the current location.  (Example,
  145. if the internal pointer is GetHandleSize( data ), then the replace string will
  146. be appended to the handle.
  147.  
  148. kActionDelete - Delete the number of characters specified by the amount field. 
  149. The internal position pointer is never moved.  If the amount field is greater
  150. than the number of characters after the internal pointer, then fewer characters
  151. are deleted such that the handle is truncated at the current value of the
  152. selection pointer.
  153.  
  154. kActionSearch - search forward (backwards if the kFlagBackwardsBit is set in
  155. the flags field) for the search field (case sensitively if the
  156. kFlagCaseSenstitiveBit is set in the flags field).  The position pointer should
  157. be set to point before the first character of the string if it is found, or at
  158. GetHandleSize (zero if backwards) if not found.  If there is a match at the
  159. initial position, it is not counted (ie, kActionMove -kMaxHandleSize, kSearch
  160. 'hello', kSearch 'hello' finds the second occurance of 'hello').
  161.  
  162. kActionSearchAndReplace - search forward (or backward if the kFlagBackwardsBit
  163. is set in the flags field), but when a match is found, replace it with the
  164. replace string, leaving the position pointer unmoved.  If the kFlagGlobalBit is
  165. set in the flags field, continue searching as long matches continues to be
  166. found.  Repeated searches begin after the previous replace string (i.e., never
  167. replace any characters of the replace string).  For example, if you replace
  168. 'aaa' with 'ABA' (case insensitively) in 'aaaaaaaa' you will get 'ABAABAaa',
  169. not 'ABABABAa'.  Replace never moves the internal position pointer.
  170.  
  171. The internal selection pointer is constrained to be in the range of 0 and
  172. GetHandleSize(data), inclusive, at all times.  Should any action cause the
  173. selection pointer to become less than zero (or greater than GetHandleSize),
  174. then you must reset it to zero (or GetHandleSize, respectively).  The handle
  175. size will never exceed 1 Meg, and you will have plenty of memory to play with.  
  176.  
  177. Characters from chr(127)-chr(255) will never appear in the handle or any
  178. strings.  
  179.  
  180.  
  181.  
  182. Problem 05 - Database
  183.  
  184. type
  185.     StringsHandle = Handle; // Sequence of Pascal Strings packed together
  186.     DatabaseHandle = Handle; // Must be a real handle
  187.     
  188. procedure DatabaseInit( var database: Handle; field_count: UInt32 );
  189. procedure DatabaseAddEntry( database: Handle; entry: StringsHandle );
  190. procedure DatabaseFindEntry( database: Handle; field: UInt32; const match:
  191. Str255; var entry: StringsHandle );
  192. procedure DatabaseDeleteEntry( database: Handle; field: UInt32; const match:
  193. Str255 );
  194. function DatabaseCount( database: Handle ): UInt32;
  195. procedure DatabaseGetIndEntry( database: Handle; index: UInt32; var entry:
  196. StringsHandle );
  197.  
  198. Your task is to write a set of routines to maintain a database.
  199.  
  200. DatabaseInit creates a new, empty database ready to accept records with
  201. field_count string fields.  The database is stored in the database Handle.
  202.  
  203. DatabaseAddEntry adds an entry (which is a Handle to field_count pascal strings
  204. packed together conceptually numbered 1 to field_count)
  205.  
  206. DatabaseFindEntry finds an entry whose field (between 1 and field_count) string
  207. is exactly equal to match.  The entry is returned in a newly created handle
  208. (which will be disposed of using DisposeHandle).  Return nil if no match is
  209. found.  If more than one entry matches, you must return the earliest added
  210. entry.
  211.  
  212. DatabaseDeleteEntry finds the entry that DatabaseFindEntry would find, and if
  213. found removes it from the database.
  214.  
  215. DatabaseCount returns the number of entries in the database.
  216.  
  217. DatabaseGetIndEntry returns the entries in the Database in the order they were
  218. entered, 1 for the earliest entered, DatabaseCount the last entered.
  219.  
  220. All the database information must be stored in the real Mac memory manager
  221. handle - it will be disposed with DisposeHandle and that must release all
  222. memory, so do not store any extra information outside the handle.  Also, you
  223. must be able to deal with having multiple databases instantiated
  224. simultaneously.
  225.  
  226. You will not be given invalid parameters so you don't need to handle error
  227. checking, and there will be plenty of memory.
  228.  
  229. All strings are case sensitive (ie, treated as eight bit binary data).
  230.  
  231.  
  232. Problem 06 - Legal Chess Moves
  233.  
  234. Deep Thought has beaten mankind as the game once thought to exemplify human
  235. intuition.  Our MacHack laboratory is secretly constructing an implant that
  236. will neutralize the calculation advantage held by the computer, and restore
  237. mankind to its rightful place as the champion of chess, through intuition and
  238. cunning.  Your job is to write the code that will calculate the board position
  239. resulting from a sequence of moves, along with the legal moves available to the
  240. next player.  With this advantage, the human chess master will be able to
  241. concentrate on strategy, rather than waste time calculating moves.
  242.  
  243. The prototype for your solution is as follows:
  244.  
  245. typedef enum {kEmpty=0,kWhite,kBlack} PieceColor;
  246. typedef enum {kNone=0,kPawn,kKnight,kBishop,kRook,kQueen,kKing} PieceRank;
  247.  
  248. typedef struct Square {
  249.     UInt16 row;    // 0..7, white initially occupies rows 0 and 1, black 7 and 6
  250.     UInt16 col;    // 0..7, white king starts at (row,col) == (0,4)
  251. } Square;
  252.  
  253. typedef struct ChessMove {
  254.     Square fromSquare;
  255.     Square toSquare;
  256.     Boolean capture;
  257.     Square capturedSquare;    // valid only if capture==TRUE
  258. } ChessMove;
  259.  
  260. typedef struct ChessPiece {
  261.     PieceColor whichColor;
  262.     PieceRank whichRank;
  263.     Square pieceLocation;
  264. } ChessPiece;
  265.  
  266. pascal void FindLegalChessMoves(
  267.     UInt32 numPriorMoves,
  268.     ChessMove priorMoves[],
  269.     UInt32 *numPiecesRemaining,
  270.     ChessPiece piecesRemaining[],
  271.     UInt32 *numLegalMoves,
  272.     ChessMove legalMoves[]
  273. );
  274.  
  275. Your FindLegalChessMoves routine will be called with a list (priorMoves) of
  276. numPriorMoves that have already taken place from the normal initial chessboard.
  277. You should model the effects of those moves and generate a list
  278. (piecesRemaining) of the numPiecesRemaining pieces remaining, including their
  279. location on the board, and a list (legalMoves) of all numLegalMoves legal moves
  280. available to the next player.  You should follow all rules of Chess with two
  281. exceptions: stalemates can be ignored, and pawns always become Queens when
  282. promoted.  Remember to include castling moves when appropriate (indicated by
  283. moving the king the appropriate two/three squares) and en passant pawn
  284. captures.
  285.  
  286.  
  287. Problem 07 - Graph
  288.  
  289. procedure GraphInit( var graph: Handle; verrticies: UInt32 );
  290. procedure GraphAddDirectedEdge( graph: Handle; vertex1, vertex2: UInt32 );
  291. procedure GraphFindRoute( graph: Handle; vertex1, vertex2: UInt32; var
  292. verticies: Handle );
  293.  
  294. Your task is to write a set of routines to create and traverse a directed
  295. graph.
  296.  
  297. GraphInit creates a new, empty directed graph ready to accept directed edges
  298. with verrticies verticies.  
  299.  
  300. GraphAddDirectedEdge adds a directed edge from vertex1 to vertex2
  301.  
  302. GraphFindRoute find a route from vertex1 to vertex2.  If such a route exists,
  303. then verticies is returns as a real Mac handle to an array of UInt32s, the
  304. first is vertex1, the last is vertex2.  Each successive vertex must have
  305. previously had an edge added with GraphAddDirectedEdge.  If no route exists,
  306. return nil for verticies.  No vertex should appear more than once in the
  307. verticies handle, except for the case where vertex1 is the same as vertex2, in
  308. which case you must find a circular route from vertex1 back to itself and so
  309. vertex1 will appear exactly twice, once at the start and once at the end of the
  310. verticies handle.
  311.  
  312. All the graph information must be stored in the real Mac memory manager handle
  313. - it will be disposed with DisposeHandle and that must release all memory, so
  314. dont store any extra information outside the handle.  Also, you must be able to
  315. deal with having multiple graphs instantiated simultaneously.
  316.  
  317.  
  318. Problem 08 - Packing
  319.  
  320. PointArray = array[0..0] of Point;
  321. PointArrayPtr = ^PointArray;
  322.  
  323. procedure PackBoxes( frame: Rect; box_count: UInt32; boxes: PointArray;
  324. toplefts: PointArrayPtr );
  325.  
  326. Your task is to pack a set of 2-dimensional boxes into a given frame rectangle
  327. such that the interior of the boxes do not intersect.
  328.  
  329. The box dimensions are represented by height (the .v component) and width (the
  330. .h component) in the boxes array.  You must find a way to fit all the
  331. rectangles inside the frame without overlapping.  Just like QuickDraw standard
  332. rectangles, two adjacent rectangles could have the same right/left coordinate,
  333. so that they are touching but not overlapping.  Similarly, rectangles may touch
  334. the edge of the frame.  When you find a solution, you should return the topleft
  335. coordinates of each rectange.  Rectangles may only be moved horrizontally or
  336. vertically, they may not be rotated.
  337.  
  338. Example
  339.  
  340. frame = (10, 10, 100, 100 )
  341. box_count = 3
  342. boxes = { (50, 90), (40, 40), (40, 50) }
  343.  
  344. return
  345.  
  346. toplefts = { (10, 10), (60, 10), (60, 50) }
  347.  
  348.  
  349.  
  350. Problem 09 - State Machine
  351.  
  352. type GetNextCharProc = function( curstate: UInt32 ): UInt32;
  353.  
  354. procedure StateMachineInit( var state_machine: Handle; states: UInt32; chars:
  355. UInt32 );
  356. procedure AddTransition( state_machine: Handle; state1, state2: UInt32;
  357. first_char, last_char: UInt32 );
  358. procedure RunStateMachine( state_machine: Handle; start_state: UInt32;
  359. GetNextChar: GetNextCharProc; var stop_state: UInt32 );
  360.  
  361. This problem requires you to maintain and operate a state machine, consisting
  362. of rules that change the current machine state based on the current input.  Our
  363. state machines do not require that you produce any output other than the
  364. machine state.
  365.  
  366. StateMachineInit creates a new, empty state machine ready to accept state
  367. transitions, and containing states states (numbers 1 to states) and chars
  368. characters (numbered 1 to chars).  All the state machine information must be
  369. stored in the real Mac memory manager handle - it will be disposed with
  370. DisposeHandle and that must release all memory, so dont store any extra
  371. information outside the handle.  Also, you must be able to deal with having
  372. multiple state machine instantiated simultaneously.
  373.  
  374. AddTransition adds a transition from state1 to state2 for characters between
  375. (inclusive) first_char and last_char.  When you get to state1 and get a
  376. character between first_char and last_char you should proceed to state2.  The
  377. new transition overrides and previous transitions for these characters from
  378. state1 (ie, if you get transition 1->2 for chars 1-10, and then 1->3 for chars
  379. 5-6, you now have transition 1->2 for chars 1-4 and 7-10 and transition 1->3
  380. for chars 5-6).
  381.  
  382. RunStateMachine starts in start_state and calls GetNextChar repeatedly until
  383. either it returns 0 or until it returns a character for which there is no
  384. transition at the current state.  Each time GerNewChar supplies a character,
  385. the current state is updated based on the transition rule that applies to that
  386. combination of current state and current input.  When GetNextChar supplies a
  387. state for which no transition rule exists, the state machine halts and the
  388. final state is returned in stop_state.
  389.  
  390. Problem 10 - Interpreter
  391.  
  392. Write an interpreter for this simple 32-bit integer language with 26 registers
  393. labeled A-Z.
  394.  
  395. type RegisterArray = array[0..25] of SInt32;
  396.  
  397. procedure Interpret( source: Handle; var result: RegisterArray );
  398.  
  399. source consists of a number of lines of the form:
  400.  
  401. [<label>:][<tab><instruction><tab><operand-list>]<cr>
  402.  
  403. <label> is a sequence of at least two alphanumerics (0-9a-zA-Z_)
  404. (casesensitive).
  405. <operand-list> is a sequence of operators seperated by commas
  406. other than the tabs and crs, no white space is allowed.
  407.  
  408. <instruction> (and appropriate operands are:
  409.  
  410. MOVE    <value>,<register>            (set <register> to <value>)
  411. ADD     <value1>,<value2>,<register>  (set <register> to <value1>+<value2>)
  412. SUB     <value1>,<value2>,<register>  (set <register> to <value1>-<value2>)
  413. JMP     <label>                       (jump to line labeled with <label>)
  414. JEQ     <value1>,<value2>,<label>     (jump to <label> if <value1> = <value2>)
  415. JLE     <value1>,<value2>,<label>     (jump to <label> if <value1> <= <value2>)
  416. JSR     <label>                       (jump to subroutine at <label>)
  417. RTS                                   (return from subroutine)
  418. PUSH    <value>                       (push value on to stack)
  419. POP     <register>                    (pop value from stack)
  420.  
  421. <register> is a single uppercase letter in the range A..Z
  422. <number> is an optional minus sign followed by decimal digits
  423. <value> is a <register> or a <number>
  424.  
  425. Note that the data stack and subroutine stack are independent stacks.  A RTS is
  426. used to stop the program (that is, consider that you have JSRed to the initial
  427. line of the source handle).  For example:
  428.  
  429.     PUSH    10
  430.     JSR    setA
  431.     JSE setB
  432.     RTS
  433. setA:
  434.     POP    A
  435.     RTS
  436. setB:    MOVE    A,B
  437.     RTS
  438.     
  439. Interpret takes the source handle and JSRs to it, presetting the registers
  440. according to the register array.  When the code returns, the register array is
  441. set to the final value of all the registers.  Both subroutine and data stacks
  442. should be large (at least 1000 entries each).
  443.  
  444. ENDENDEND
  445.